const express = require('express');
const bodyParser = require("body-parser");
const app = express();
const cookieParser = require('cookie-parser');
const WebSocketServer = require('ws').Server;
const url = require("url");

app.use(cookieParser());

//设置跨域访问
app.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", ' 3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

//设置访问文件格式
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded

//配置服务端口
let server = app.listen(8080, function () {

    let port = server.address().port;

    console.log(`应用实例，访问地址为${port}端口`);

});

/*随机字符*/
function uuid(len, radix) {
    let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    let uuid = [];
    radix = radix || chars.length;

    if (len) {
        for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
    } else {
        let r;

        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';

        for (let i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | Math.random() * 36;
                uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
            }
        }
    }

    return uuid.join('');
}

let nameId = 0;
/*端口默认访问地址*/
app.get('/', function (req, res) {
    let uuId = uuid(10);
    res.cookie('nameId', nameId);
    res.cookie('user', uuId);
    res.set('Content-Type', 'text/html');
    res.sendFile(__dirname + '/HTML/index.html');
    console.log(`=================设置cookie nameId=${nameId} user=${uuId}完成=================`);
    nameId += 1;
});


function parseUser(obj) {
    if (!obj) {
        return;
    }

    let {cookie} = obj;
    return {
        name: getCookie(cookie, 'user'),
        id: getCookie(cookie, 'nameId'),
    };

    //return user;
}

/*查找cookie*/
function getCookie(cookie, cookieName) {
    try {
        let c_start = cookie.indexOf(cookieName);
        if (c_start !== -1) {
            c_start = c_start + cookieName.length + 1;
            let c_end = cookie.indexOf(";", c_start);
            if (c_end === -1) c_end = cookie.length;
            cookie = cookie.substring(c_start, c_end);
        }
        return cookie;
    } catch (e) {
        console.log(e);
        console.log('错误');
    }
}

function createWebSocketServer(server, onConnection, onMessage, onClose, onError) {
    let wss = new WebSocketServer({
        server: server
    });
    wss.broadcast = function broadcast(data) {
        let {clients} = wss;
        clients.forEach(function (client) {
            client.send(data);
        });
    };
    /*默认值*/
    onConnection = onConnection || function () {
        console.log('[WebSocket] connected.');
    };
    onMessage = onMessage || function (msg) {
        console.log('[WebSocket] message received: ' + msg);
    };
    onClose = onClose || function (code, message) {
        console.log(`[WebSocket] closed: ${code} - ${message}`);
    };
    onError = onError || function (err) {
        console.log('[WebSocket] error: ' + err);
    };
    wss.on('connection', function (ws, req) {
        let location = url.parse(req.url, true);
        console.log('[WebSocketServer] connection: ' + location.href);
        if (location.pathname !== '/ws/chat') {
            // close ws:
            ws.close(4000, 'Invalid URL');
            console.log('url错误');
            return;
        }
        // check user:
        let user = parseUser(req.headers);
        console.log(user);
        if (!user || user.name === undefined) {
            ws.close(4001, 'Invalid user');
            console.log('没拿到cookie');
            return;
        }
        ws.on('message', onMessage);
        ws.on('close', onClose);
        ws.on('error', onError);
        ws.user = user;
        ws.wss = wss;
        onConnection.apply(ws);
    });
    console.log('WebSocketServer附加完成.');
    return wss;
}

let messageIndex = 0;

/*构建数据*/
function createMessage(type, user, data) {
    messageIndex++;
    return JSON.stringify({
        id: messageIndex,
        type: type,
        user: user,
        data: data
    });
}

function onConnect() {
    let user = this.user;
    let msg = createMessage('join', user, `${user.name} 加入.`);
    this.wss.broadcast(msg);
    // build user list:
    let {clients} = this.wss;
    let arr = [];
    let flag = 0;
    clients.forEach((client) => {
        arr[flag] = client.user;
        flag += 1;
    });
    console.log('===========打印结果和时间===========');
    console.log(formatDateTime(new Date()));
    console.log(arr);
    this.send(createMessage('list', user, arr));
}

/*收到消息*/
function onMessage(message) {
    console.log(message);
    if (message && message.trim()) {
        let msg = createMessage('chat', this.user, message.trim());
        this.wss.broadcast(msg);
    }
}

/*关闭连接*/
function onClose() {
    let user = this.user;
    let msg = createMessage('left', user, `${user.name} is 离开.`);
    this.wss.broadcast(msg);
}

app.wss = createWebSocketServer(server, onConnect, onMessage, onClose);

let formatDateTime = function (date) {
    let y = date.getFullYear();
    let m = date.getMonth() + 1;
    m = m < 10 ? `0${m}` : m;
    let d = date.getDate();
    d = d < 10 ? `0${d}` : d;
    let h = date.getHours();
    let minute = date.getMinutes();
    minute = minute < 10 ? `0${minute}` : minute;
    return `${y}-${m}-${d} ${h}:${minute}`;
};